package com.monitor.app_monitor.service.quartz.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPathException;
import com.monitor.app_monitor.entity.PmEmsInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;


@Slf4j
@Service
public class ExecuteScript {

    @Resource
    @Qualifier("dataAnalysisThreadPool")
    private ThreadPoolExecutor threadPoolExecutor;


    public ScriptExecResult executeScript(String script, String wgName , String rs ,String dataPath) throws Exception {
        final String scriptPath = script;
        final boolean exists = new File(scriptPath).exists();
        if (!exists) {
            log.error("脚本不存在");
            throw new ScriptNotExistsException();
        }
        String command = "bash";
        //数据文件存储路径

        StringBuilder commandStr = new StringBuilder();
        commandStr.append(command)
                .append(" ")
                .append(scriptPath)
                .append(" ")
                .append(dataPath)
                .append("/")
                .append(wgName)
                .append("/")
                .append(rs);
        final String finallyCommand =commandStr.toString();
        log.info("执行脚本参数：{},{},{},{}",script, wgName, rs, dataPath);
        log.info("执行脚本命令为:{}",commandStr.toString());
        log.info("最终执行命令：",finallyCommand);
        final Process process = Runtime.getRuntime().exec(commandStr.toString());

        final Future<ScriptExecResult> successResult =
                this.threadPoolExecutor.submit((Callable<ScriptExecResult>) () -> {
                    final StringBuilder resultInfo = new StringBuilder();
                    InputStream inputStream = null;
                    try  {
                        inputStream = process.getInputStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) > 0) {
                            resultInfo.append(new String(buffer, 0, len));
                        }
                        final String result = resultInfo.toString();
                        return JSON.parseObject(result, ScriptExecResult.class);
                    } catch (JSONPathException e) {
                        log.error("解析脚本返回结果失败 script=>{}", commandStr);
                    } finally {
                        inputStream.close();
                    }
                    return ScriptExecResult.errorResult();
                });

        final Future<ScriptExecResult> errorResult =
                this.threadPoolExecutor.submit((Callable<ScriptExecResult>) () -> {
                    StringBuilder errorInfo = new StringBuilder();
                    InputStream errorStream = null;
                    try {
                        errorStream = process.getErrorStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = errorStream.read(buffer)) > 0) {
                            errorInfo.append(new String(buffer, 0, len));
                        }
                        final StringBuilder error = errorInfo;
                        if (error.length() > 0) {
                            log.info("读取错误信息=>{}", error);
                        }
                    } catch (Exception e) {
                        log.error("执行脚本错误1 errorResult=>{}", commandStr.toString());
                        log.error(e.toString());
                    }finally {
                        errorStream.close();
                    }
                    return ScriptExecResult.errorResult();
                });

        //等待执行完成
        process.waitFor();
        //获取返回数据
        try {
            final ScriptExecResult scriptExecResult = successResult.get();
            return scriptExecResult;
        } catch (Exception e) {
            final ScriptExecResult scriptExecResult = errorResult.get();
            return scriptExecResult;
        } finally {
            process.destroy();
        }

    }

    public FileinfoScriptExecResult executeFileInfoScript(String script, String wgName , String rs ,String dataPath) throws Exception {
        final String scriptPath = script;
        final boolean exists = new File(scriptPath).exists();
        if (!exists) {
            log.error("脚本不存在");
            throw new ScriptNotExistsException();
        }
        String command = "bash";
        //数据文件存储路径

        StringBuilder commandStr = new StringBuilder();
        commandStr.append(command)
                .append(" ")
                .append(scriptPath)
                .append(" ")
                .append(dataPath)
                .append("/")
                .append(wgName)
                .append("/")
                .append(rs);

        final String finallyCommand =commandStr.toString();
        final Process process = Runtime.getRuntime().exec(finallyCommand);

        log.info("一干采集文件是否完成脚本：{}",finallyCommand);
        final Future<FileinfoScriptExecResult> successResult =
                this.threadPoolExecutor.submit((Callable<FileinfoScriptExecResult>) () -> {
                    final StringBuilder resultInfo = new StringBuilder();
                    InputStream inputStream = null;
                    try {
                        inputStream = process.getInputStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) > 0) {
                            resultInfo.append(new String(buffer, 0, len));
                        }
                        final String result = resultInfo.toString();
                        return JSON.parseObject(result, FileinfoScriptExecResult.class);
                    } catch (JSONPathException e) {
                        log.error("解析脚本返回结果失败 script=>{}", commandStr);
                    } finally {
                        inputStream.close();
                    }
                    return FileinfoScriptExecResult.errorResult();
                });

        final Future<FileinfoScriptExecResult> errorResult =
                this.threadPoolExecutor.submit((Callable<FileinfoScriptExecResult>) () -> {
                    StringBuilder errorInfo = new StringBuilder();
                    InputStream errorStream = null;
                    try {
                        errorStream = process.getErrorStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = errorStream.read(buffer)) > 0) {
                            errorInfo.append(new String(buffer, 0, len));
                        }
                        final StringBuilder error = errorInfo;
                        if (error.length() > 0) {
                            log.info("读取错误信息=>{}", error);
                        }
                    } catch (Exception e) {
                        log.error("执行脚本错误2 errorResult=>{}", commandStr.toString());
                        log.error(e.toString());
                    } finally {
                        errorStream.close();
                    }
                    return FileinfoScriptExecResult.errorResult();
                });

        //等待执行完成
        process.waitFor();
        //获取返回数据
        try {
            final FileinfoScriptExecResult scriptExecResult = successResult.get();
            return scriptExecResult;
        } catch (Exception e) {
            final FileinfoScriptExecResult scriptExecResult = errorResult.get();
            return scriptExecResult;
        } finally {
            process.destroy();
        }

    }

    public FileinfoScriptExecResult executeRgFileInfoScript(String script, String filePath) throws Exception {
        final String scriptPath = script;
        final boolean exists = new File(scriptPath).exists();
        if (!exists) {
            log.error("脚本不存在");
            throw new ScriptNotExistsException();
        }
        String command = "bash";
        //数据文件存储路径

        StringBuilder commandStr = new StringBuilder();
        commandStr.append(command)
                .append(" ")
                .append(scriptPath)
                .append(" ")
                .append(filePath);

        final String finallyCommand =commandStr.toString();
        final Process process = Runtime.getRuntime().exec(finallyCommand);


        final Future<FileinfoScriptExecResult> successResult =
                this.threadPoolExecutor.submit((Callable<FileinfoScriptExecResult>) () -> {
                    final StringBuilder resultInfo = new StringBuilder();
                    InputStream inputStream = null;

                    try  {
                        inputStream = process.getInputStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) > 0) {
                            resultInfo.append(new String(buffer, 0, len));
                        }
                        final String result = resultInfo.toString();
                        return JSON.parseObject(result, FileinfoScriptExecResult.class);
                    } catch (JSONPathException e) {
                        log.error("解析脚本返回结果失败 script=>{}", commandStr);
                    } finally {
                        inputStream.close();
                    }
                    return FileinfoScriptExecResult.errorResult();
                });

        final Future<FileinfoScriptExecResult> errorResult =
                this.threadPoolExecutor.submit((Callable<FileinfoScriptExecResult>) () -> {
                    StringBuilder errorInfo = new StringBuilder();
                    InputStream errorStream = null;

                    try {
                        errorStream = process.getErrorStream();

                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = errorStream.read(buffer)) > 0) {
                            errorInfo.append(new String(buffer, 0, len));
                        }
                        final StringBuilder error = errorInfo;
                        if (error.length() > 0) {
                            log.info("读取错误信息=>{}", error);
                        }
                    } catch (Exception e) {
                        log.error("执行脚本错误3 errorResult=>{}", commandStr.toString());
                        log.error(e.toString());
                    }finally {
                        errorStream.close();
                    }
                    return FileinfoScriptExecResult.errorResult();
                });

        //等待执行完成
        process.waitFor();
        //获取返回数据
        try {
            final FileinfoScriptExecResult scriptExecResult = successResult.get();
            return scriptExecResult;
        } catch (Exception e) {
            final FileinfoScriptExecResult scriptExecResult = errorResult.get();
            return scriptExecResult;
        } finally {
            process.destroy();
        }

    }


    public IsUpdataScriptExecResult IsUpdataScript(String script, String ipAddr , String port ) throws Exception {
        final String scriptPath = script;
        final boolean exists = new File(scriptPath).exists();
        if (!exists) {
            log.error("脚本不存在");
            throw new ScriptNotExistsException();
        }
        String command = "bash";
        //数据文件存储路径

        StringBuilder commandStr = new StringBuilder();
        commandStr.append(command)
                .append(" ")
                .append(scriptPath)
                .append(" ")
                .append(ipAddr)
                .append(" ")
                .append(port);

        final String finallyCommand =commandStr.toString();
        final Process process = Runtime.getRuntime().exec(finallyCommand);

        final Future<IsUpdataScriptExecResult> successResult =
                this.threadPoolExecutor.submit((Callable<IsUpdataScriptExecResult>) () -> {
                    final StringBuilder resultInfo = new StringBuilder();
                    InputStream inputStream = null;
                    try {
                        inputStream = process.getInputStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) > 0) {
                            resultInfo.append(new String(buffer, 0, len));
                        }
                        final String result = resultInfo.toString();
                        return JSON.parseObject(result, IsUpdataScriptExecResult.class);
                    } catch (JSONPathException e) {
                        log.error("解析脚本返回结果失败 script=>{}", commandStr);
                    } finally {
                        inputStream.close();
                    }
                    return IsUpdataScriptExecResult.errorResult();
                });

        final Future<IsUpdataScriptExecResult> errorResult =
                this.threadPoolExecutor.submit((Callable<IsUpdataScriptExecResult>) () -> {
                    StringBuilder errorInfo = new StringBuilder();
                    InputStream errorStream = null;
                    try {
                        errorStream = process.getErrorStream();
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = errorStream.read(buffer)) > 0) {
                            errorInfo.append(new String(buffer, 0, len));
                        }
                        final StringBuilder error = errorInfo;

                        if (error.length() > 0) {
                            log.info("读取错误信息=>{}", error);
                        }
                    } catch (Exception e) {
                        log.error("执行脚本错误4 errorResult=>{}", commandStr.toString());
                        log.error(e.toString());
                    } finally {
                        errorStream.close();
                    }
                    return IsUpdataScriptExecResult.errorResult();
                });

        //等待执行完成
        process.waitFor();
        //获取返回数据
        try {
            final IsUpdataScriptExecResult scriptExecResult = successResult.get();
            return scriptExecResult;
        } catch (Exception e) {
            final IsUpdataScriptExecResult scriptExecResult = errorResult.get();
            return scriptExecResult;
        } finally {
            process.destroy();
        }

    }

    public PmEmsInfo executePmScript(String script) throws Exception {
        final String scriptPath = script;
        final boolean exists = new File(scriptPath).exists();
        if (!exists) {
            log.error("脚本不存在");
            throw new ScriptNotExistsException();
        }
        String command = "bash";
        //数据文件存储路径

        StringBuilder commandStr = new StringBuilder();
        commandStr.append(scriptPath);
//                .append(" ")
//                .append(scriptPath);
        final String finallyCommand =commandStr.toString();
        log.info("开始执行脚本 =>{}", finallyCommand);
        final Process process = Runtime.getRuntime().exec(finallyCommand);

        final Future<PmEmsInfo> successResult =
                this.threadPoolExecutor.submit((Callable<PmEmsInfo>) () -> {
                    final StringBuilder resultInfo = new StringBuilder();
                    try (
                            InputStream inputStream = process.getInputStream();
                    ) {
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) > 0) {
                            resultInfo.append(new String(buffer, 0, len));
                        }
                        final String result = resultInfo.toString();
                        return JSON.parseObject(result, PmEmsInfo.class);
                    } catch (JSONPathException e) {
                        log.error("解析脚本返回结果失败 script=>{}", commandStr);
                    }
                    return PmEmsInfo.errorResult();
                });

        final Future<PmEmsInfo> errorResult =
                this.threadPoolExecutor.submit((Callable<PmEmsInfo>) () -> {
                    StringBuilder errorInfo = new StringBuilder();

                    try (
                            InputStream errorStream = process.getErrorStream()
                    ) {
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = errorStream.read(buffer)) > 0) {
                            errorInfo.append(new String(buffer, 0, len));
                        }
                        final StringBuilder error = errorInfo;
                        log.info("读取错误信息=>{}", error);
                    } catch (Exception e) {
                        log.error("执行脚本错误 errorResult=>{}", script);
                    }
                    return PmEmsInfo.errorResult();
                });

        //等待执行完成
        process.waitFor();
        //获取返回数据
        try {
            final PmEmsInfo scriptExecResult = successResult.get();
            //log.info("脚本执行完成,返回结果=>{}", scriptExecResult);
            return scriptExecResult;
        } catch (Exception e) {
            final PmEmsInfo scriptExecResult = errorResult.get();
            return scriptExecResult;
        } finally {
            process.destroy();
        }

    }

    public Integer executePmNceSScript() throws Exception {


        StringBuilder commandStr = new StringBuilder();
        commandStr.append("bash /home/deployer/bin/PmDir.py");
        final String finallyCommand =commandStr.toString();
        log.info("开始执行脚本 =>{}", finallyCommand);
        final Process process = Runtime.getRuntime().exec(finallyCommand);

        final Future<Integer> successResult =
                this.threadPoolExecutor.submit((Callable<Integer>) () -> {
                    final StringBuilder resultInfo = new StringBuilder();
                    try (
                            InputStream inputStream = process.getInputStream();
                    ) {
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) > 0) {
                            resultInfo.append(new String(buffer, 0, len));
                        }

                        final Integer result = Integer.valueOf(resultInfo.toString());
                        log.info("解析脚本返回结果失败PM {}" ,result);
                        return result;
                    } catch (JSONPathException e) {
                        log.error("解析脚本返回结果失败 script=>{}", commandStr);
                    }
                    return null;
                });

        final Future<Integer> errorResult =
                this.threadPoolExecutor.submit((Callable<Integer>) () -> {
                    StringBuilder errorInfo = new StringBuilder();

                    try (
                            InputStream errorStream = process.getErrorStream()
                    ) {
                        final byte[] buffer = new byte[1024 * 8];
                        int len = 0;
                        while ((len = errorStream.read(buffer)) > 0) {
                            errorInfo.append(new String(buffer, 0, len));
                        }
                        final StringBuilder error = errorInfo;
                        log.info("读取错误信息=>{}", error);
                    } catch (Exception e) {
                        log.error("执行脚本错误 errorResult=>{}");
                    }
                    return null;
                });

        //等待执行完成
        process.waitFor();
        //获取返回数据
        //fff
        try {
            final Integer scriptExecResult = successResult.get();
            log.info("1脚本执行完成,返回结果=>{}", scriptExecResult);
            return scriptExecResult;
        } catch (Exception e) {
            final Integer scriptExecResult = errorResult.get();
            log.info("2脚本执行完成,返回结果=>{}", scriptExecResult);
            e.printStackTrace();
            return scriptExecResult;
        } finally {
            process.destroy();
        }

    }

    public static long getLineNumber(File file) {
        if (file.exists()) {
            try {
                FileReader fileReader = new FileReader(file);
                LineNumberReader lineNumberReader = new LineNumberReader(fileReader);
                lineNumberReader.skip(Long.MAX_VALUE);
                long lines = lineNumberReader.getLineNumber();
                fileReader.close();
                lineNumberReader.close();
                return lines;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

}
